package lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author bc
 * @Description:
 * @date 2024/03/11
 */
public class MyReentrantLock implements Lock {

    private static class Sync extends AbstractQueuedSynchronizer {

        @Override
        protected boolean tryAcquire(int arg) {
            int state = getState();

            //如果state为0 说明没锁
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }

            //如果线程和当前占用锁的线程一致，线程重入 锁+1
            if (Thread.currentThread() == getExclusiveOwnerThread()) {
                compareAndSetState(state, state + 1);
                return true;
            }

            //返回false，线程会加入到同步队列进行等待
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            //只有拿到锁的线程会进入 只有一个线程会调用
            int state = getState();

            //进行-1操作
            setState(state - 1);

            //如果为0，表明完全释放，把当前占用锁的线程设置为null
            if (getState() == 0) {
                setExclusiveOwnerThread(null);
            }

            return true;
        }

        /**
         * 判断是否占用
         */
        @Override
        protected boolean isHeldExclusively() {
            return getState() > 0;
        }
    }

    private Sync sync = new Sync();

    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return tryLock();
    }

    @Override
    public void unlock() {
        sync.tryRelease(1);
    }

    @Override
    public Condition newCondition() {
        return null;
    }

    public boolean isLock() {
        return sync.isHeldExclusively();
    }
}
